package com.huawei.cloudphone.apiimpl;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;

import com.huawei.cloudphone.api.CloudPhoneClipboardListener;
import com.huawei.cloudphone.common.CASLog;

public class CloudPhoneImeMgr {
    private static final String TAG = "CloudPhoneImeMgr";

    private static final int TEXT_SIZE = 14;
    private static final int TEXT_MAX_LEN = 40;
    private static final int TEXT_MAX_LINES = 1;
    private static final int BOX_INPUT_HEIGHT = 1;
    private static final int BUTTON_WIDTH = 65;
    private static final int BUTTON_HEIGHT = 40;
    private static final int IME_MSG_SHOW = 0;
    private static final int IME_MSG_HIDE = 1;
    private static final int IME_MSG_TEXT = 2;
    private static final int IME_KEY_EVENT = 3;
    private static final int IME_PASTE_FROM_CLOUD = 6;
    private static final int IME_PASTE_TO_CLOUD = 7;
    private static final int IME_MSG_HEADER_LEN = 3;
    private static final int IME_KEY_EVENT_LEN = 2;

    private ViewGroup mRootViewGroup;
    private ViewGroup mImeViewGroup;
    private Context mContext;
    private EditText mImeEditText;
    private PopupWindow mPopWindow;
    private CloudPhoneTextWatchListener mTextWatchListener;
    private CloudPhoneClipboardListener mClipboardListener;

    @SuppressLint("Range")
    public CloudPhoneImeMgr(Context context, ViewGroup viewGroup) {
        mContext = context;
        mRootViewGroup = viewGroup;

        mImeViewGroup = new RelativeLayout(context);
        RelativeLayout.LayoutParams  imeViewGroupLp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, dip2px(BOX_INPUT_HEIGHT));
        imeViewGroupLp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        mImeViewGroup.setLayoutParams(imeViewGroupLp);
        mImeViewGroup.setBackgroundColor(Color.TRANSPARENT);
        mImeViewGroup.setAlpha(50);
        
        mImeEditText = new EditText(context);
        RelativeLayout.LayoutParams imeEditTextLp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
        mImeEditText.setLayoutParams(imeEditTextLp);
        mImeEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
        mImeEditText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
        mImeEditText.setTextSize(TypedValue.COMPLEX_UNIT_PX, dip2px(TEXT_SIZE));
        mImeEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(TEXT_MAX_LEN)});
        mImeEditText.setMaxLines(TEXT_MAX_LINES);
        mImeViewGroup.addView(mImeEditText);

        mImeEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                String text = charSequence.toString();
                if (text.isEmpty()) {
                    return;
                }
                byte[] data = text.getBytes();
                byte[] msg = new byte[IME_MSG_HEADER_LEN + data.length];
                msg[0] = IME_MSG_TEXT;
                msg[1] = (byte) ((data.length >> 8) & 0xFF);
                msg[2] = (byte) (data.length & 0XFF);

                System.arraycopy(data, 0, msg, 3, data.length);
                if (mTextWatchListener != null) {
                    mTextWatchListener.onTextChange(msg);
                }
                mImeEditText.setText("");
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

        mImeEditText.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
                if (keyCode == KeyEvent.KEYCODE_DEL && keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
                    byte[] msg = new byte[IME_MSG_HEADER_LEN + IME_KEY_EVENT_LEN];
                    msg[0] = IME_KEY_EVENT;
                    msg[1] = (byte) ((IME_KEY_EVENT_LEN >> 8) & 0xFF);
                    msg[2] = (byte) (IME_KEY_EVENT_LEN & 0XFF);
                    msg[3] = (byte) ((KeyEvent.KEYCODE_DEL >> 8) & 0xFF);
                    msg[4] = (byte) (KeyEvent.KEYCODE_DEL & 0XFF);

                    if (mTextWatchListener != null) {
                        mTextWatchListener.onTextChange(msg);
                    }
                    return true;
                }
                return false;
            }
        });

        mPopWindow = new PopupWindow(mImeViewGroup, WindowManager.LayoutParams.MATCH_PARENT, dip2px(BOX_INPUT_HEIGHT), true);
        mPopWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        mPopWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        mPopWindow.setOutsideTouchable(true);
        mPopWindow.setTouchable(true);
    }

    public int show(String text) {
        if (mPopWindow.isShowing()) {
            return 0;
        }
        mImeEditText.getText().clear();
        mPopWindow.setFocusable(true);
        mImeEditText.requestFocus();
        mPopWindow.showAtLocation(mRootViewGroup, Gravity.BOTTOM, 0, 0);

        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                InputMethodManager inputMethodManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                inputMethodManager.showSoftInput(mImeEditText, 0);
            }
        }, 100);
        return 0;
    }

    public synchronized int hide() {
        if (!mPopWindow.isShowing()) {
            return 0;
        }
        mPopWindow.dismiss();
        InputMethodManager inputMethodManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(mImeEditText.getWindowToken(), 0);
        return 0;
    }

    public void processImeMsg(byte[] data) {
        if (data == null) {
            return;
        }
        final byte type = data[0];
        int msgLen = (data[1] << 8) | (data[2] & 0xFF);
        String text = null;
        if (msgLen > 0) {
            text = new String(data,3, msgLen);
        }
        final String finalText = text;
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                switch (type) {
                    case IME_MSG_SHOW:
                        showKeyBoard(true, finalText);
                        break;
                    case IME_MSG_HIDE:
                        showKeyBoard(false, null);
                    case IME_PASTE_FROM_CLOUD:
                        setClipBoard(finalText);
                    default:
                        break;
                }
            }
        });
    }

    public void setTextWatchListener(CloudPhoneTextWatchListener listener) {
        mTextWatchListener = listener;
    }

    public void setClipboardListener(CloudPhoneClipboardListener listener) {
        mClipboardListener = listener;
    }

    public void sendClipboardData(byte[] data) {
        byte[] msg = new byte[IME_MSG_HEADER_LEN + data.length];
        msg[0] = IME_PASTE_TO_CLOUD;
        msg[1] = (byte) ((data.length >> 8) & 0xFF);
        msg[2] = (byte) (data.length & 0XFF);

        System.arraycopy(data, 0, msg, 3, data.length);
        if (mTextWatchListener != null) {
            mTextWatchListener.onTextChange(msg);
        }
    }

    private void showKeyBoard(boolean isShow, String text) {
        if (isShow) {
            this.show(text);
        } else {
            this.hide();
        }
    }

    private void setClipBoard(String text) {
        if (text != null && mClipboardListener != null) {
            mClipboardListener.onClipboardChange(text.getBytes());
        }
    }

    private int dip2px(float dipValue) {
        final float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }
}